<template>
  <div class="chat-input-area">
    <!-- 编辑器容器 -->
    <div
      :class="['edit-chat-container', isEmpty ? '' : 'not-empty']"
      contenteditable="true"
      @paste.prevent="onPaste"
      @keydown="onKeydown"
      @compositionstart="compositionFlag = true"
      @compositionend="onCompositionEnd"
      @input="onEditorInput"
      @mousedown="onMousedown"
      ref="content"
      @blur="onBlur"
      class="editor-padding-right"
    ></div>

    <!-- @提及弹窗 -->
    <chat-at-box
      @select="onAtSelect"
      :search-text="atSearchText"
      ref="atBox"
      :ownerId="ownerId"
      :members="groupMembers"
    ></chat-at-box>

    <!-- 上传进度条 -->
    <div class="upload-progress" v-if="uploadProgress > 0 && uploadProgress < 100">
      <div class="progress-bar" :style="{ width: uploadProgress + '%' }"></div>
      <div class="progress-text">{{ uploadProgress }}%</div>
    </div>
  </div>
</template>

<script>
import ChatAtBox from "../Common/ChatAtBox";
import service from "../../utils/request";
// 消息类型常量定义（与后端保持一致）
export const MESSAGE_TYPES = {
  TEXT: 0,
  IMAGE: 1,
  FILE: 2,
  VOICE: 6,
  QUOTE: 11
};

export default {
  name: "ChatInput",
  components: { ChatAtBox },
  props: {
    ownerId: { type: Number, default: 0 },
    groupMembers: { type: Array, default: () => [] },
    // 语音配置参数（支持外部传入）
    maxVoiceDuration: { type: Number, default: 60 }, // 最大录音时长（秒）
    minVoiceDuration: { type: Number, default: 1 }, // 最小录音时长（秒）
    maxFileSize: { type: Number, default: 50 }, // 最大文件大小（MB）
    supportedImageTypes: {
      type: Array,
      default: () => ["image/jpeg", "image/png", "image/gif", "image/webp"]
    },
    // 当前引用信息（来自父组件）
    currentQuote: {
      type: Object,
      default: null
    },
    // 是否显示语音按钮
    showVoiceButton: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      // 媒体列表
      imageList: {},
      fileList: {},
      voiceList: {},

      // 编辑器状态
      currentId: 0,
      atSearchText: null,
      compositionFlag: false,
      atIng: false,
      isEmpty: true,
      changeStored: true,
      blurRange: null,
      uploadProgress: 0,
      isQuoteInserted: false,

      // 语音相关状态
      voiceService: null,
      isRecording: false,
      isVoiceDisabled: false,
      showMicError: false,
      micErrorMsg: "",
      recordingTime: 0,
      recordingTimer: null,
      volumeLevels: [],
      isRecordingOverMax: false,
      startY: 0, // 录音开始时的Y坐标（用于上滑取消）
      // 消息类型常量
      MESSAGE_TYPES
    };
  },
  computed: {},
  watch: {
    // 监听引用信息变化，自动插入到编辑器
    currentQuote(newVal) {
      if (newVal && !this.isQuoteInserted) {
        this.insertQuoteElement(newVal);
        this.isQuoteInserted = true;
      } else if (!newVal) {
        this.removeQuoteElement();
        this.isQuoteInserted = false;
      }
    }
  },
  mounted() {
    // 初始化编辑器默认内容 - 使用$nextTick确保DOM已渲染
    this.$nextTick(() => {
      this.empty();
    });
  },
  beforeDestroy() {
    if (this.recordingTimer) {
      clearInterval(this.recordingTimer);
    }
  },
  methods: {
    // 插入引用消息元素
    insertQuoteElement(quoteInfo) {
      // 创建引用容器
      const quoteContainer = document.createElement("div");
      quoteContainer.className = "chat-quote-container no-text";
      quoteContainer.contentEditable = "false";
      quoteContainer.dataset.quoteId = quoteInfo.messageId;

      // 引用内容
      const quoteContent = document.createElement("div");
      quoteContent.className = "chat-quote-content";
      quoteContent.innerHTML = `
        <div class="quote-sender">${quoteInfo.senderNickname}:</div>
        <div class="quote-text">${this.formatQuoteContent(quoteInfo)}</div>
      `;

      quoteContainer.appendChild(quoteContent);

      // 插入到编辑器
      this.focus();
      this.updateRange();
      const blurRange = this.blurRange;

      if (
        blurRange.startContainer !== blurRange.endContainer ||
        blurRange.startOffset !== blurRange.endOffset
      ) {
        blurRange.deleteContents();
      }

      blurRange.insertNode(quoteContainer);
      blurRange.collapse();

      // 插入换行
      const br = document.createElement("br");
      blurRange.insertNode(br);
      blurRange.collapse();

      this.updateRange();
      this.isEmpty = false;
    },

    // 格式化引用内容
    formatQuoteContent(quoteInfo) {
      switch (quoteInfo.messageType) {
        case MESSAGE_TYPES.TEXT:
          return quoteInfo.content || "";
        case MESSAGE_TYPES.IMAGE:
          return "[图片]";
        case MESSAGE_TYPES.FILE:
          return `[文件: ${quoteInfo.mediaName || "未知文件"}]`;
        case MESSAGE_TYPES.VOICE:
          return `[语音 ${quoteInfo.duration || 0}秒]`;
        case MESSAGE_TYPES.QUOTE:
          return `[引用] ${quoteInfo.content || ""}`;
        default:
          return `[${this.getMessageTypeName(quoteInfo.messageType)}]`;
      }
    },

    // 获取消息类型名称
    getMessageTypeName(type) {
      const typeMap = {
        [MESSAGE_TYPES.TEXT]: "文本",
        [MESSAGE_TYPES.IMAGE]: "图片",
        [MESSAGE_TYPES.FILE]: "文件",
        [MESSAGE_TYPES.VOICE]: "语音",
        [MESSAGE_TYPES.QUOTE]: "引用"
      };
      return typeMap[type] || "消息";
    },

    // 移除引用元素
    removeQuoteElement() {
      const quoteEl = this.$refs.content.querySelector(".chat-quote-container");
      if (quoteEl) {
        quoteEl.remove();
        this.isEmpty = this.$refs.content.innerHTML.trim() === "";
      }
    },

    // 粘贴处理
    onPaste(e) {
      this.isEmpty = false;
      let txt = e.clipboardData.getData("Text");
      let range = window.getSelection().getRangeAt(0);
      if (
        range.startContainer !== range.endContainer ||
        range.startOffset !== range.endOffset
      ) {
        range.deleteContents();
      }

      // 粘贴文本
      if (txt && typeof txt == "string") {
        let textNode = document.createTextNode(txt);
        range.insertNode(textNode);
        range.collapse();
        return;
      }

      // 粘贴图片和文件
      let items = (e.clipboardData || window.clipboardData).items;
      if (items.length) {
        for (let i = 0; i < items.length; i++) {
          if (items[i].type.indexOf("image") !== -1) {
            // 处理图片
            let file = items[i].getAsFile();
            this.handleImagePaste(file, range);
          } else {
            // 处理文件
            let asFile = items[i].getAsFile();
            if (asFile) {
              this.handleFilePaste(asFile, range);
            }
          }
        }
      }
      range.collapse();
    },

    // 处理粘贴的图片
    handleImagePaste(file, range) {
      // 验证图片类型
      if (!this.supportedImageTypes.includes(file.type)) {
        this.$emit(
          "error",
          `不支持的图片类型，仅支持${this.supportedImageTypes.join(", ")}`
        );
        return;
      }

      // 验证图片大小
      if (file.size > this.maxFileSize * 1024 * 1024) {
        this.$emit("error", `图片大小不能超过${this.maxFileSize}MB`);
        return;
      }

      let imagePush = {
        fileId: this.generateId(),
        file: file,
        rawFile: file, // 添加原始文件引用
        name: file.name, // 添加文件名
        size: file.size, // 添加文件大小
        url: URL.createObjectURL(file),
        messageType: MESSAGE_TYPES.IMAGE
      };
      this.imageList[imagePush.fileId] = imagePush;

      let line = this.newLine();
      let imageElement = document.createElement("img");
      imageElement.className = "chat-image no-text";
      imageElement.src = imagePush.url;
      imageElement.dataset.imgId = imagePush.fileId;
      line.appendChild(imageElement);
      let after = document.createTextNode("\u00A0");
      line.appendChild(after);
      this.selectElement(after, 1);
    },

    // 处理粘贴的文件
    handleFilePaste(file, range) {
      // 验证文件大小
      if (file.size > this.maxFileSize * 1024 * 1024) {
        this.$emit("error", `文件大小不能超过${this.maxFileSize}MB`);
        return;
      }

      let filePush = {
        fileId: this.generateId(),
        file: file,
        rawFile: file, // 添加原始文件引用
        name: file.name, // 添加文件名
        size: file.size, // 添加文件大小
        messageType: MESSAGE_TYPES.FILE
      };
      this.fileList[filePush.fileId] = filePush;

      let line = this.newLine();
      let fileElement = this.createFile(filePush);
      line.appendChild(fileElement);

      let after = document.createTextNode("\u00A0");
      line.appendChild(after);
      this.selectElement(after, 1);
    },
    // 选择元素 - 添加安全检查
    selectElement(element, endOffset) {
      const selection = window.getSelection();
      // 确保元素存在于DOM中
      if (!element || !document.contains(element)) {
        return;
      }

      // 使用$nextTick确保DOM已更新
      this.$nextTick(() => {
        try {
          const range = document.createRange();
          range.setStart(element, 0);
          range.setEnd(element, endOffset || 0);
          if (element.firstChild) {
            range.selectNodeContents(element.firstChild);
          }
          range.collapse();
          selection.removeAllRanges();
          selection.addRange(range);
          // 需要时自动聚焦
          if (element.focus) {
            element.focus();
          }
        } catch (error) {
          console.error("选择元素时出错:", error);
          // 出错时尝试重新设置编辑器焦点
          this.focus();
        }
      });
    },

    // 中文输入结束
    onCompositionEnd(e) {
      this.compositionFlag = false;
      this.onEditorInput(e);
    },

    // 键盘事件处理
    onKeydown(e) {
      if (e.keyCode === 13) {
        e.preventDefault();
        e.stopPropagation();
        if (this.atIng) {
          this.$refs.atBox.select();
          return;
        }
        if (e.ctrlKey) {
          let line = this.newLine();
          let after = document.createTextNode("\u00A0");
          line.appendChild(after);
          this.selectElement(line.childNodes[0], 0);
        } else {
          // 中文输入标记
          if (this.compositionFlag) {
            return;
          }
          this.submit();
        }
        return;
      }
      // 删除键
      if (e.keyCode === 8) {
        // 等待dom更新
        setTimeout(() => {
          let s = this.$refs.content.innerHTML.trim();
          // 空dom时，需要刷新dom
          if (s === "" || s === "<br>" || s === "<div>&nbsp;</div>") {
            // 拼接随机长度的空格，以刷新dom
            this.empty();
            this.isEmpty = true;
            this.selectElement(this.$refs.content);
          } else {
            this.isEmpty = false;
          }
        });
      }
      // at框打开时，上下键移动特殊处理
      if (this.atIng) {
        if (e.keyCode === 38) {
          e.preventDefault();
          e.stopPropagation();
          this.$refs.atBox.moveUp();
        }
        if (e.keyCode === 40) {
          e.preventDefault();
          e.stopPropagation();
          this.$refs.atBox.moveDown();
        }
      }
    },
    // @选择处理
    onAtSelect(member) {
      this.atIng = false;
      // 选中输入的 @xx 符
      let blurRange = this.blurRange;
      let endContainer = blurRange.endContainer;
      let startOffset = endContainer.data.indexOf("@" + this.atSearchText);
      let endOffset = startOffset + this.atSearchText.length + 1;
      blurRange.setStart(blurRange.endContainer, startOffset);
      blurRange.setEnd(blurRange.endContainer, endOffset);
      blurRange.deleteContents();
      blurRange.collapse();
      this.focus();
      // 创建元素节点
      let element = document.createElement("SPAN");
      element.className = "chat-at-user";
      element.dataset.id = member.userInfoId;
      element.contentEditable = "false";
      element.innerText = `@${member.username}`;
      blurRange.insertNode(element);
      // 光标移动到末尾
      blurRange.collapse();
      // 插入空格
      let textNode = document.createTextNode("\u00A0");
      blurRange.insertNode(textNode);
      blurRange.collapse();
      this.atSearchText = "";
      this.selectElement(textNode, 1);
    },

    // 编辑器输入事件
    onEditorInput(e) {
      this.isEmpty = false;
      this.changeStored = false;
      if (this.$props.groupMembers && !this.compositionFlag) {
        let selection = window.getSelection();
        // 检查是否有有效的选择范围
        if (selection.rangeCount === 0) {
          return;
        }
        let range = selection.getRangeAt(0);
        // 截取@后面的名称作为过滤条件，并以空格结束
        let endContainer = range.endContainer;
        let endOffset = range.endOffset;
        let textContent = endContainer.textContent;
        let startIndex = -1;
        for (let i = endOffset; i >= 0; i--) {
          if (textContent[i] === "@") {
            startIndex = i;
            break;
          }
        }
        // 没有at符号，则关闭弹窗
        if (startIndex === -1) {
          this.$refs.atBox.close();
          return;
        }

        let endIndex = endOffset;
        for (let i = endOffset; i < textContent.length; i++) {
          if (textContent[i] === " ") {
            endIndex = i;
            break;
          }
        }
        this.atSearchText = textContent
          .substring(startIndex + 1, endIndex)
          .trim();
        // 打开选择弹窗
        if (this.atSearchText == "") {
          this.showAtBox(e);
        }
      }
    },

    // 失去焦点事件
    onBlur(e) {
      if (!this.atIng) {
        this.updateRange();
      }
    },

    // 鼠标按下事件
    onMousedown() {
      if (this.atIng) {
        this.$refs.atBox.close();
        this.atIng = false;
      }
    },

    // 插入表情
    insertEmoji(emojiText) {
      let emojiElement = document.createElement("img");
      emojiElement.className = "emoji-normal no-text";
      emojiElement.dataset.emojiCode = emojiText;
      emojiElement.src = this.$emo.textToUrl(emojiText);

      let blurRange = this.blurRange;
      if (!blurRange) {
        this.focus();
        this.updateRange();
        blurRange = this.blurRange;
      }
      if (
        blurRange.startContainer !== blurRange.endContainer ||
        blurRange.startOffset !== blurRange.endOffset
      ) {
        blurRange.deleteContents();
      }
      blurRange.insertNode(emojiElement);
      blurRange.collapse();

      let textNode = document.createTextNode("\u00A0");
      blurRange.insertNode(textNode);
      blurRange.collapse();

      this.selectElement(textNode);
      this.updateRange();
      this.isEmpty = false;
    },

    // 生成唯一ID
    generateId() {
      return this.currentId++;
    },

    // 创建文件元素
    createFile(filePush) {
      let file = filePush.file;
      let fileId = filePush.fileId;
      let container = document.createElement("div");
      container.className = "chat-file-container no-text";
      container.contentEditable = "false";
      container.dataset.fileId = fileId;

      let left = document.createElement("div");
      left.className = "file-position-left";
      container.appendChild(left);

      let icon = document.createElement("div");
      icon.className = "el-icon-document";
      left.appendChild(icon);

      let right = document.createElement("div");
      right.className = "file-position-right";
      container.appendChild(right);

      let fileName = document.createElement("div");
      fileName.className = "file-name";
      fileName.innerText = file.name;

      let fileSize = document.createElement("div");
      fileSize.className = "file-size";
      fileSize.innerText = this.sizeConvert(file.size);

      right.appendChild(fileName);
      right.appendChild(fileSize);

      return container;
    },

    // 大小转换
    sizeConvert(len) {
      if (len < 1024) {
        return len + "B";
      } else if (len < 1024 * 1024) {
        return (len / 1024).toFixed(2) + "KB";
      } else if (len < 1024 * 1024 * 1024) {
        return (len / 1024 / 1024).toFixed(2) + "MB";
      } else {
        return (len / 1024 / 1024 / 1024).toFixed(2) + "GB";
      }
    },

    // 更新光标位置 - 添加范围检查
    updateRange() {
      const selection = window.getSelection();
      // 检查选择对象是否有有效的范围
      if (selection.rangeCount > 0) {
        this.blurRange = selection.getRangeAt(0);
      } else {
        // 如果没有有效范围，创建一个新的范围
        this.blurRange = document.createRange();
        const content = this.$refs.content;
        if (content.firstChild) {
          this.blurRange.setStart(content.firstChild, 0);
          this.blurRange.setEnd(content.firstChild, 0);
        }
      }
    },

    // 新建行
    newLine() {
      let selection = window.getSelection();
      // 检查是否有有效的选择范围
      if (selection.rangeCount === 0) {
        const range = document.createRange();
        const content = this.$refs.content;
        if (content.firstChild) {
          range.setStartAfter(content.firstChild);
          range.setEndAfter(content.firstChild);
        } else {
          range.setStart(content, 0);
          range.setEnd(content, 0);
        }
        selection.addRange(range);
      }
      let range = selection.getRangeAt(0);
      let divElement = document.createElement("div");
      let endContainer = range.endContainer;
      let parentElement = endContainer.parentElement;
      if (parentElement.parentElement === this.$refs.content) {
        divElement.innerHTML = endContainer.textContent
          .substring(range.endOffset)
          .trim();
        endContainer.textContent = endContainer.textContent.substring(
          0,
          range.endOffset
        );
        // 插入到当前div（当前行）后面
        parentElement.insertAdjacentElement("afterend", divElement);
      } else {
        divElement.innerHTML = "";
        this.$refs.content.append(divElement);
      }
      return divElement;
    },

    // 清空编辑器
    clear() {
      this.empty();
      this.imageList = {};
      this.fileList = {};
      this.voiceList = {};
      this.$refs.atBox.close();
    },

    // 初始化空编辑器 - 确保正确设置选择范围
    empty() {
      this.$refs.content.innerHTML = "";
      let line = this.newLine();
      let after = document.createTextNode("\u00A0");
      line.appendChild(after);

      // 使用$nextTick确保DOM更新后再设置选择范围
      this.$nextTick(() => {
        const selection = window.getSelection();
        const range = document.createRange();

        // 确保元素存在再设置范围
        if (after.parentNode) {
          range.setStart(after, 0);
          range.setEnd(after, 0);
          selection.removeAllRanges();
          selection.addRange(range);
        }
      });
    },

    // 显示@弹窗
    showAtBox(e) {
      this.atIng = true;
      let selection = window.getSelection();
      // 检查是否有有效的选择范围
      if (selection.rangeCount === 0) {
        return;
      }

      let range = selection.getRangeAt(0);

      // 光标所在坐标
      let pos = range.getBoundingClientRect();

      this.$refs.atBox.open({
        x: pos.x,
        y: pos.y
      });
      // 记录光标所在位置
      this.updateRange();
    },
    // 提交消息
    submit() {
      //初始化输出数据
      const messageData = {
        messageType: 0, // 0-文本 1-图片 2-文件 6-语音
        content: "", // 文本内容
        extInfo: {},
        atUserIds: [], // @用户ID列表
        // rawFile: null, // 原始文件对象
        // mediaUrl: "", // 临时预览URL
        // mediaName: "", // 文件名
        // mediaSize: 0, // 文件大小
        // duration: 0 // 语音时长
      };

      //获取编辑器内容DOM
      const contentDom = this.$refs.content;
      if (!contentDom) return;

      //遍历DOM节点解析内容
      let tempText = "";
      const traverse = nodes => {
        Array.from(nodes).forEach(node => {
          if (!node) return;

          // 文本节点
          if (node.nodeType === 3) {
            tempText += node.textContent;
            return;
          }

          const nodeName = node.nodeName.toLowerCase();
          if (nodeName === "script") return;

          // 图片节点
          if (nodeName === "img") {
            // 处理图片表情
            if (node.dataset.emojiCode) {
              tempText += node.dataset.emojiCode;
              return;
            }
            // 处理上传图片
            const imgId = node.dataset.imgId;
            if (imgId && this.imageList[imgId]) {
              const imgInfo = this.imageList[imgId];

              messageData.messageType = 1; // 图片类型
              messageData.extInfo = imgInfo;
              // messageData.rawFile = imgInfo.file;
              // messageData.mediaUrl = imgInfo.url;
              // messageData.mediaName = imgInfo.name || "image.png";
              // messageData.mediaSize = imgInfo.size || 0;
            }
          }

          // 文件节点
          else if (nodeName === "div") {
            // 语音消息
            if (node.dataset.voiceId) {
              const voiceId = node.dataset.voiceId;
              if (this.voiceList[voiceId]) {
                const voiceInfo = this.voiceList[voiceId];
                messageData.messageType = 6; // 语音类型
                messageData.extInfo = voiceInfo;
                // messageData.rawFile = voiceInfo.rawFile;
                // messageData.mediaUrl = voiceInfo.url;
                // messageData.mediaName = voiceInfo.name || "voice.wav";
                // messageData.mediaSize = voiceInfo.size || 0;
                // messageData.duration = voiceInfo.duration || 0;
              }
            }
            // 普通文件
            else if (node.dataset.fileId) {
              const fileId = node.dataset.fileId;
              if (this.fileList[fileId]) {
                const fileInfo = this.fileList[fileId];
                messageData.messageType = 2; // 文件类型
                messageData.extInfo = fileInfo;
                // messageData.rawFile = fileInfo.rawFile;
                // messageData.mediaUrl = fileInfo.url;
                // messageData.mediaName = fileInfo.name || "file";
                // messageData.mediaSize = fileInfo.size || 0;
              }
            }
            // 换行处理
            else {
              tempText += "\n";
              traverse(node.childNodes);
            }
          }

          // @用户节点
          else if (nodeName === "span" && node.dataset.id) {
            tempText += node.innerHTML;
            messageData.atUserIds.push(node.dataset.id);
          }

          // 其他节点处理
          else if (node.outerHTML) {
            tempText += node.outerHTML;
          }
        });
      };

      // 执行遍历解析
      traverse(contentDom.childNodes);

      // 4. 处理文本内容
      messageData.content = tempText.trim();
      // 去重@用户ID
      messageData.atUserIds = [...new Set(messageData.atUserIds)];
      // 若没有媒体文件且有文本，标记为文本类型
      if (messageData.messageType === 0 && messageData.content) {
        messageData.messageType = 0;
      }

      // 5. 提交给父组件
      this.$emit("submit", messageData);
      // 清空编辑器
      this.clear();
    },

    // 验证消息有效性
    isValidMessage(messageData) {
      switch (messageData.messageType) {
        case MESSAGE_TYPES.TEXT:
          return (
            messageData.content.trim().length > 0 ||
            messageData.atUserIds.length > 0
          );
        case MESSAGE_TYPES.IMAGE:
        case MESSAGE_TYPES.FILE:
        case MESSAGE_TYPES.VOICE:
          return !!messageData.mediaUrl;
        case MESSAGE_TYPES.QUOTE:
          return (
            !!messageData.quote &&
            (messageData.content.trim().length > 0 ||
              messageData.atUserIds.length > 0)
          );
        default:
          return false;
      }
    },

    // 聚焦编辑器
    focus() {
      this.$refs.content.focus();
    }
  }
};
</script>

<style lang="scss">
.chat-input-area {
  width: 100%;
  height: 100%;
  position: relative;
  min-height: 100px;

  // 语音录制按钮
  .voice-record-btn {
    position: absolute;
    right: 10px;
    bottom: 10px;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background-color: #f53f3f;
    color: white;
    border: none;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 10;
    transition: all 0.2s;

    &.disabled {
      background-color: #ccc;
      cursor: not-allowed;
    }

    &.recording {
      background-color: #ff4d4f;
      box-shadow: 0 0 15px rgba(255, 77, 79, 0.5);
    }

    .voice-icon {
      font-size: 20px;
      margin-bottom: 3px;
      width: 24px;
      height: 24px;
      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3zm0 14a5 5 0 0 1-5 5v2a7 7 0 0 0 14 0v-2a5 5 0 0 1-5-5z'/%3E%3C/svg%3E");
      background-repeat: no-repeat;
      background-position: center;
    }

    .voice-icon.recording-icon {
      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 14H9V8h2v8zm4 0h-2V8h2v8z'/%3E%3C/svg%3E");
    }

    .voice-text {
      font-size: 12px;
      line-height: 1;
    }
  }

  .edit-chat-container {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    outline: none;
    padding: 5px;
    line-height: 26px;
    font-size: 14px;
    text-align: left;
    overflow-y: auto;
    border: 1px solid #e5e7eb;
    border-radius: 6px;

    // 单独一行时，无法在前面输入的bug
    > div:before {
      content: "\00a0";
      font-size: 14px;
      position: absolute;
      top: 0;
      left: 0;
    }

    .chat-image {
      display: block;
      max-width: 200px;
      max-height: 100px;
      border: 1px solid #e6e6e6;
      cursor: pointer;
      margin: 5px 0;
      border-radius: 4px;
    }

    .chat-file-container {
      max-width: 65%;
      padding: 10px;
      border: 2px solid #587ff0;
      display: flex;
      background: #eeec;
      border-radius: 10px;
      margin: 5px 0;

      .file-position-left {
        display: flex;
        width: 80px;
        justify-content: center;
        align-items: center;

        .el-icon-document {
          font-size: 40px;
          text-align: center;
          color: #d42e07;
        }
      }

      .file-position-right {
        flex: 1;

        .file-name {
          font-size: 16px;
          font-weight: 600;
          color: #66b1ff;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }

        .file-size {
          font-size: 14px;
          color: #666;
        }
      }
    }

    .chat-voice-container {
      max-width: 200px;
      padding: 8px 12px;
      background-color: #f5f5f5;
      border-radius: 20px;
      display: flex;
      align-items: center;
      margin: 5px 0;
      cursor: pointer;
      transition: background-color 0.2s;

      &:hover {
        background-color: #eeeeee;
      }

      .voice-play-icon {
        width: 24px;
        height: 24px;
        margin-right: 10px;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23666'%3E%3Cpath d='M8 5v14l11-7z'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: center;
      }

      .voice-progress-container {
        flex: 1;
        height: 2px;
        background-color: #ddd;
        border-radius: 1px;
        overflow: hidden;

        .voice-progress-bar {
          height: 100%;
          width: 0%;
          background-color: #1890ff;
        }
      }

      .voice-duration {
        margin-left: 10px;
        font-size: 12px;
        color: #666;
      }
    }

    .chat-at-user {
      color: #0066cc;
      background-color: #e6f7ff;
      padding: 0 3px;
      border-radius: 3px;
      margin: 0 2px;
    }

    .emoji-normal {
      width: 24px;
      height: 24px;
      vertical-align: middle;
      margin: 0 1px;
    }
  }

  .edit-chat-container > div:nth-of-type(1):after {
    content: "请输入消息（按Ctrl+Enter键换行）";
    color: gray;
  }

  .edit-chat-container.not-empty > div:nth-of-type(1):after {
    content: none;
  }

  // 语音录制弹窗
  .voice-recording-popup {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 220px;
    height: 220px;
    background-color: rgba(0, 0, 0, 0.8);
    border-radius: 50%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    color: white;

    .recording-circle {
      width: 80px;
      height: 80px;
      border-radius: 50%;
      background-color: #ff4d4f;
      margin-bottom: 15px;
      display: flex;
      align-items: center;
      justify-content: center;
      animation: pulse 1.5s infinite;

      &.warning {
        background-color: #faad14;
        animation: warning 1s infinite alternate;
      }
    }

    .recording-time {
      font-size: 20px;
      margin-bottom: 10px;
      font-weight: bold;
    }

    .volume-wave {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 3px;
      height: 30px;
      margin-bottom: 10px;

      .volume-bar {
        display: inline-block;
        width: 3px;
        background-color: white;
        border-radius: 1px;
        transition: height 0.1s ease;
      }
    }

    .recording-tip {
      font-size: 14px;
      text-align: center;
      max-width: 180px;
    }
  }

  // 麦克风错误提示
  .mic-error-alert {
    position: absolute;
    top: 10px;
    left: 10px;
    right: 10px;
    background-color: #fff1f0;
    border: 1px solid #ffa39e;
    border-radius: 8px;
    padding: 12px;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    color: #cf1322;
    z-index: 5;

    .error-icon {
      font-size: 18px;
      margin-top: 1px;
    }

    .error-content {
      flex: 1;

      h4 {
        font-size: 14px;
        margin: 0 0 5px;
        font-weight: 600;
      }

      p {
        font-size: 13px;
        margin: 0 0 8px;
        line-height: 1.4;
      }

      .fix-btn {
        background-color: #ff4d4f;
        color: white;
        border: none;
        padding: 4px 10px;
        border-radius: 4px;
        cursor: pointer;
        font-size: 13px;
        transition: background-color 0.2s;

        &:hover {
          background-color: #f5222d;
        }
      }
    }
  }

  // 上传进度条
  .upload-progress {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 3px;
    background-color: #eee;
    z-index: 10;
    overflow: hidden;

    .progress-bar {
      height: 100%;
      background-color: #1890ff;
      transition: width 0.3s ease;
    }

    .progress-text {
      position: absolute;
      right: 5px;
      top: -20px;
      font-size: 12px;
      color: #666;
      background-color: white;
      padding: 0 3px;
      border-radius: 2px;
    }
  }

  // 引用消息样式
  .chat-quote-container {
    border-left: 2px solid #1890ff;
    padding: 8px 12px;
    margin: 5px 0;
    background-color: #f5f7fa;
    border-radius: 4px;
    font-size: 13px;

    .quote-sender {
      color: #8c8c8c;
      font-weight: 500;
      margin-bottom: 4px;
    }

    .quote-text {
      color: #595959;
      word-break: break-all;

      &.quote-image {
        color: #1890ff;
      }
    }
  }
}

// 动画
@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(255, 77, 79, 0.7);
  }
  70% {
    box-shadow: 0 0 0 10px rgba(255, 77, 79, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(255, 77, 79, 0);
  }
}

@keyframes warning {
  from {
    box-shadow: 0 0 0 0 rgba(250, 173, 20, 0.7);
  }
  to {
    box-shadow: 0 0 0 8px rgba(250, 173, 20, 0.4);
  }
}

/* 提取的内联样式 */
.editor-padding-right {
  padding-right: 80px;
}
</style>
    